#pragma once

#include "task_base.h"
#include "application/vehicle/vehicle_service.h"
#include "application/map/map_application_service.h"
#include "application/map/lift/base_lift.h"
#include "lift_strategy.h"
#include <memory>
#include <string>

namespace application {
namespace dispatcher { class DispatcherService; }
namespace task {

/**
 * @brief 电梯任务 - AGV使用电梯跨楼层移动
 * @details 对应三方代码中的 TaskLift (task_lift.cpp)
 *
 *          核心流程（使用责任链模式）：
 *
 *          1. QueryStatus - 查询电梯状态
 *             - 请求电梯状态
 *             - 等待响应（IDLE）
 *             - 重试机制（reset_cnt > 3 则关门重置）
 *
 *          2. Call - 呼叫电梯
 *             - 发送呼叫请求（call_floor -> aim_floor）
 *             - 等待响应
 *             - 重试机制（reset_cnt > RESENDCNT）
 *
 *          3. ArrivedCallFloor - 到达呼叫楼层
 *             - 检查电梯是否到达呼叫楼层
 *             - 等待门打开
 *             - AGV开始移动进入电梯
 *
 *          4. InLift - 进入电梯
 *             - 检查AGV是否进入电梯内部点（interPoint）
 *             - 发送关门请求
 *             - 等待电梯开始移动
 *
 *          5. ArrivedAimFloor - 到达目标楼层
 *             - 检查电梯是否到达目标楼层
 *             - 等待门打开
 *             - AGV开始移动出电梯
 *
 *          6. OutLift - 离开电梯
 *             - 检查AGV是否离开到等待点（waitPoint）
 *             - 发送关门请求
 *             - 任务完成
 *
 *          注意：
 *          - HKLift（海康电梯）：使用TCP协议控制电梯
 *          - MKLM电梯：通过AGV的Script任务（switchMap.py）切换楼层，不需要独立电梯API
 *          - 本任务仅支持HKLift，MKLM跨楼层通过MoveTask+Script实现
 */
class LiftTask : public SubTaskBase {
public:
    /**
     * @brief 构造函数
     * @param vehicleService 车辆服务
     * @param mapService 地图服务
     * @param logger 日志记录器
     * @param liftNum 电梯编号
     * @param callFloor 呼叫楼层
     * @param targetFloor 目标楼层
     */
    LiftTask(
        std::shared_ptr<vehicle::VehicleService> vehicleService,
        std::shared_ptr<MapApplicationService> mapService,
        std::shared_ptr<dispatcher::DispatcherService> dispatcherService,
        std::shared_ptr<kernel::ILogger> logger,
        int liftNum,
        int callFloor,
        int targetFloor
    );

    ~LiftTask() override = default;

    // SubTaskBase 接口实现
    kernel::task::TaskStage init(TaskContext& ctx) override;
    kernel::task::TaskStage run(TaskContext& ctx) override;
    kernel::task::TaskStage cleanup(TaskContext& ctx) override;

    kernel::task::TaskType getType() const override {
        return kernel::task::TaskType::Lift;
    }

    std::string getDescription() const override {
        return "Lift: floor " + std::to_string(m_callFloor) +
               " -> " + std::to_string(m_targetFloor);
    }

    std::string getCallAskPointStation() const {
        return m_callFloorInfo.askPoint.toStdString();
    }

    int getCallFloor() const {
        return m_callFloor;
    }

private:
    std::shared_ptr<vehicle::VehicleService> m_vehicleService;
    std::shared_ptr<MapApplicationService> m_mapService;
    std::shared_ptr<dispatcher::DispatcherService> m_dispatcherService;
    int m_lastAgvNumber{-1};

    // 电梯参数
    int m_liftNum;
    int m_callFloor;
    int m_targetFloor;

    // 电梯指针
    std::shared_ptr<lift::BaseLift> m_lift;
    lift::LiftType m_liftType{lift::LiftType::Unknown};
    lift::FloorInfo m_callFloorInfo;
    lift::FloorInfo m_targetFloorInfo;
    QString m_callMapName;
    QString m_targetMapName;

    LiftContext m_liftCtx;
    std::unique_ptr<BaseLiftStrategy> m_strategy;

    bool requestLift(TaskContext& ctx,
                     bool& liftUnavailable,
                     bool& askPointNotReached,
                     bool& targetWaitConflict);
    void releaseDispatcherRoutes(int agvNumber);

    bool ensureCallAreaReservations(TaskContext& ctx);
    bool reserveTargetWaitArea(TaskContext& ctx);
    bool occupyArea(const QString& areaId,
                    int floor,
                    bool& occupiedFlag,
                    const char* label,
                    TaskContext& ctx);
    void releaseArea(const QString& areaId,
                     int floor,
                     bool& occupiedFlag,
                     const char* label,
                     TaskContext& ctx);
    void releaseCallAreas(TaskContext& ctx);
    void releaseCallWaitArea(TaskContext& ctx);
    void releaseTargetWaitArea(TaskContext& ctx);

    bool m_callAskAreaOccupied{false};
    bool m_callWaitAreaOccupied{false};
    bool m_targetWaitAreaOccupied{false};
    bool m_callAreasPrepared{false};
    bool m_dispatcherRoutesCleared{false};
};

} // namespace task
} // namespace application
